package main

import (
	stderrors "errors"
	"fmt"
	"gitee.com/bei_yi_ning/gorder/common"
	client "gitee.com/bei_yi_ning/gorder/common/client/order"
	"gitee.com/bei_yi_ning/gorder/common/consts"
	"gitee.com/bei_yi_ning/gorder/common/handler/errors"
	"gitee.com/bei_yi_ning/gorder/order/app"
	"gitee.com/bei_yi_ning/gorder/order/app/command"
	"gitee.com/bei_yi_ning/gorder/order/app/dto"
	"gitee.com/bei_yi_ning/gorder/order/app/query"
	"gitee.com/bei_yi_ning/gorder/order/convertor"
	"github.com/gin-gonic/gin"
)

// 实现了serverinterface ，其中接口通过openapi生成
type HTTPServer struct {
	common.BaseResponse
	app app.Application
}

func (H HTTPServer) PostCustomerCustomerIdOrders(c *gin.Context, customerID string) {

	var (
		req  client.CreateOrderRequest
		err  error
		resp dto.CreateOrderResponse
	)
	defer func() {
		H.Response(c, err, &resp)
	}()

	// 这里的反序列化的坑需要尤其注意
	// req字段被tag标注，那只能按tag来
	// 但是tag对首字母大小写不敏感，它到时候大写小写都能对上
	// 因此Customer_id 可以被正确序列化到req的customer_id上
	// 无论是Items还是items都能序列化到req的items上
	if err := c.ShouldBindJSON(&req); err != nil {
		err = errors.NewWithError(consts.ErrnoBindRequestError, err)
		return
	}
	// 对req进行参数校验
	if err = H.validate(req); err != nil {
		err = errors.NewWithError(consts.ErrnoRequestValidateError, err)
		return
	}

	result, err := H.app.Commands.CreateOrder.Handle(c.Request.Context(), command.CreateOrder{
		CustomerID: req.CustomerId,
		Items:      convertor.NewItemWithQuantityConvertor().ClientsToEntities(req.Items),
	})
	if err != nil {
		return
	}
	resp = dto.CreateOrderResponse{
		CustomerID:  req.CustomerId,
		OrderID:     result.OrderID,
		RedirectURL: fmt.Sprintf("http://localhost:8282/success?customerID=%s&orderID=%s", req.CustomerId, result.OrderID),
	}
}

func (H HTTPServer) GetCustomerCustomerIdOrdersOrderId(c *gin.Context, customerID string, orderID string) {
	var (
		err  error
		resp struct {
			Order *client.Order
		}
	)
	defer func() {
		H.Response(c, err, resp)
	}()
	o, err := H.app.Queries.GetCustomerOrder.Handle(c.Request.Context(), query.GetCustomerOrder{
		CustomerID: customerID,
		OrderID:    orderID,
	})
	if err != nil {
		return
	}
	resp.Order = convertor.NewOrderConvertor().EntityToClient(o)
}

func (H HTTPServer) validate(req client.CreateOrderRequest) error {
	pass := true
	retErr := ""
	for _, item := range req.Items {
		if item.Quantity <= 0 {
			pass = false
			retErr += fmt.Sprintf("Quantity of productID %s must be positive, now we have %d\n", item.Id, item.Quantity)
		}
	}
	if !pass {
		return stderrors.New(retErr)
	}
	return nil
}
